package advanced.network;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * TCP 网络编程
 * <p>
 * <p>
 * 使用基于tcp协议的Socket网络编程实现
 * <p>
 * Tcp协议基于请求响应模式
 * <p>
 * 在网络通讯中, 第一次主动发起通讯的程序称作客户端
 * <p>
 * 第一次通讯中等待连接的程序被称作服务器端Server程序
 * 利用IO 流实现数据的传输
 */
public class L_TCP {
    public static void main(String[] args) {
        new Thread(new TcpServer(8988)).start();
        new Thread(new TcpClient("localhost", 8988)).start();
        new Thread(new TcpClient("localhost", 8988)).start();
        new Thread(new TcpClient("localhost", 8988)).start();
        new Thread(new TcpClient("localhost", 8988)).start();
        new Thread(new TcpClient("localhost", 8988)).start();
    }
}

/**
 * 创建流程:
 * 1. 指定端口, 使用ServerSocket创建服务器
 * 2. 阻塞式等待连接accept
 * 3. 操作:输入输出流
 */
class TcpServer implements Runnable, SocketTool {
    private ServerSocket server = null;

    public TcpServer(int port) {
        try {
            server = new ServerSocket(port);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        boolean flag = true;
        while (flag) {
            try {
                Socket client = server.accept();
                if (client != null) {
                    System.out.println("一个客户端建立了连接");
                }
                DataInputStream dis = new DataInputStream(client.getInputStream());
                String msg = dis.readUTF();
                System.out.println("the msg from client = " + Thread.currentThread().getName() + " |" + msg);
                //服务端收到信息, 作出相应
                DataOutputStream dos = new DataOutputStream(client.getOutputStream());
                dos.writeUTF("服务器已收到数据");
                dos.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public void sendMsg(String msg) {

    }

    public String receive() {
        return "";
    }
}

class TcpClient implements Runnable, SocketTool {
    private Socket client = null;


    public TcpClient(String serverHost, int serverPort) {
        try {
            //建立与服务器的连接,指定服务器地址和端口
            client = new Socket(serverHost, serverPort);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        try {
            DataOutputStream dos = new DataOutputStream(client.getOutputStream());
            dos.writeUTF("hello");
            dos.flush();
            DataInputStream dis = new DataInputStream(client.getInputStream());
            String backMsg = dis.readUTF();
            System.out.println("from server: " + backMsg);
        } catch (IOException e) {
            e.printStackTrace();
        }

        try {
            client.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void sendMsg(String msg) {

    }

    public String receive() {
        return "";
    }
}

interface SocketTool {
    void sendMsg(String msg);

    String receive();
}
